using System.IO;
using HardMock;
using HardMock.Domain;
using Xunit;

namespace AcceptanceTests
{
    public class Prerequisites
    {
        #region Domain
        public interface IGoodInterface
        {
            IGoodInterface Do();
            string Do(IGoodInterface goodInterface);
        }

        public class NotSerializable : IGoodInterface
        {
            public IGoodInterface Do()
            {
                return new NotSerializable();
            }

            public string Do(IGoodInterface goodInterface)
            {
                return "pouet";
            }
        }

        private interface IToRecord
        {
            bool IsPouet(string toCompare);
        }

        class ToRecord : IToRecord
        {
            public bool IsPouet(string toCompare)
            {
                return toCompare == "pouet";
            }
        }
        #endregion

        [Fact]
        public void Fail_when_type_to_record_is_not_interface()
        {
            var ex = Assert.Throws<HardMockException>(() => new ToRecord().AsRecorder());

            Assert.Equal(string.Format("type {0} should be an interface", typeof(ToRecord).FullName), ex.Message);
        }

        [Fact]
        public void Fail_if_interface_to_record_is_not_public()
        {
            var ex = Assert.Throws<HardMockException>(() => new ToRecord().AsRecorder<IToRecord>());

            Assert.Equal(string.Format("type {0} should be public", typeof(IToRecord).FullName), ex.Message);
        }

        [Fact]
        public void Fail_if_type_is_not_serializable()
        {
            var recorder = new NotSerializable().AsRecorder<IGoodInterface>();
            var ex = Assert.Throws<HardMockException>(() =>
                                                      {
                                                          Assert.NotNull(recorder.Do());
                                                          using (var stream = new MemoryStream())
                                                          {
                                                              recorder.Snapshot(stream);
                                                          }
                                                      });

            Assert.Equal(string.Format("Type 'AcceptanceTests.Prerequisites+NotSerializable' in Assembly '{0}' is not marked as serializable.", GetType().Assembly.FullName), ex.Message);
        }

        [Fact]
        public void Fail_if_parameter_type_is_not_serializable()
        {
            var recorder = new NotSerializable().AsRecorder<IGoodInterface>();
            var ex = Assert.Throws<HardMockException>(() => Assert.NotNull(recorder.Do(new NotSerializable())));

            Assert.Equal(string.Format("Type 'AcceptanceTests.Prerequisites+NotSerializable' in Assembly '{0}' is not marked as serializable.", GetType().Assembly.FullName), ex.Message);
        }
    }
}
